#include "Tracer.h"

Color4 rayTracer::trace(ray3 r, int depth)
{
	// Stop if maximum depth of recursion has been reached.
	if (depth > MAXDEPTH)
    {
        return Color4(0.0, 0.0, 0.0, 0.0);
    }
	// Else prepare to calculate closest intersection.
	int		index     = -1;				  // Initialize to invalid index.
	double  mindst    = MAXDST + 1.0;  // Initialize to out of reach.
    Point3 collisionPt;
    Point3 collisionNorm;
	// Get closest intersection with any object
	for (int i = 0; i < pObjLst.size(); i++)
	{
		double intTime;
		Point3 intPoint;
		Point3 intNorm;
		// Find interception
        PlaneObject * o = ( PlaneObject * ) (pObjLst.at(i));
        o->getColor();

        o->Test();
        o->getIntercept(r.origin(), r.direction(), &intTime, &intPoint, &intNorm);
		(pObjLst.at(i))->getIntercept(r.origin(), r.direction(), &intTime, &intPoint, &intNorm);

		// Check if it's the closest
		if (intTime < mindst && intTime > 0.0)
		{
			index  = i;
			mindst = intTime;
            //CONSIDER
            collisionPt = intPoint;
            collisionNorm = intNorm;
		}

	}



	// If no intercept found or goes farther than max distance
	if (index < 0 || mindst > MAXDST)
    {
        return Color4(0.0, 0.0, 0.0, 0.0);
    }


	//return pObjLst.at(index)->getColor();
	// Calculate reflected ray

	// Spawn ray to light sources
	Color4 ambient, diffuse, specular, reflective, result;


    //create fake rays for light testing
    Color4 resultColor(0,0,0,1);

	for (int i = 0; i < pLightLst.size(); i++)
	{
		// (*pLightLst[i]->getIntercept(r.origin(), r.direction(), &intTime);
		Point3 lightLoc = pLightLst.at(i).getLocation();
        Point3 toLightVec;
        subtractPoints( lightLoc, collisionPt, &toLightVec );

        int objectIndex = -1;
        double minTime = MAXDST + 1.0;  // Initialize to out of reach.
		// Check for intersections with objects for shadows
		for (int j = 0; j < pObjLst.size(); j++)
		{
		    double intTime;
		    Point3 intPoint;
		    Point3 intNorm;
		    // Find interception
			pObjLst.at(j)->getIntercept(collisionPt, toLightVec, &intTime, &intPoint, &intNorm);

		    // Check if it's the closest
		    if (intTime < minTime && intTime > 0.0)
		    {
			    objectIndex  = j;
			    minTime = intTime;
                //CONSIDER
                collisionPt = intPoint;
		    }
		}

        //No shadow
        if ( objectIndex == -1 )
        {
            double lightFactor = lightEquation( r.direction(), collisionPt, collisionNorm, pLightLst.at(i).getLocation() );
            Color4 partialResult = multiplyColors( pObjLst.at(index)->getColor(),
                                                    pLightLst.at(i).getColor(),
                                                    lightFactor * pLightLst.at(i).getIntensity() );
            addTwoColors( partialResult, &resultColor );
        }
        //if in shadow, nothing; hard shadows

	}

    if( pObjLst.at(index)->getReflectance() < EPSILON )
    {
        return resultColor;
    }
    else
    {
        //handle reflection
        //Get Reflected vector
        Point3 reflected;
        reflectVector( r.direction(), collisionNorm, &reflected );
        ray3 newRay = ray3( collisionPt, reflected );
        Color4 reflectedColor = trace(newRay, depth+1);

        Color4 sumColor[2];
        sumColor[0] = resultColor;
        sumColor[1] = reflectedColor;
        double colorDivision[2];
        colorDivision[0] = 1 - pObjLst.at(index)->getReflectance();
        colorDivision[1] = pObjLst.at(index)->getReflectance();

        return addColors( sumColor, colorDivision, 2);

    }

	// Calculate reflective component
	
	// Combine lighting factors

	// Return pixel coloration
	return result;
}